#!/usr/bin/python
#
# Copyright (c) 2018 Dell Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
#
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
#

import sys
import subprocess
import os
import argparse
import traceback

_map_level_to_int={
    'debug':'7',
    'info':'6',
    'notice':'5',
    'warning':'4',
    'error':'3',
    'critical':'2',
    'alert':'1',
     'emerg':'0'
    }


def __log_enable_to_string(level):
    if int(level) == 0:
        return 'Disable'
    return 'Enable'

parser = argparse.ArgumentParser(description='This tool will update the logging configuration file.  To apply changes to a running application you need to send a kill -USR1 pid')
parser.add_argument('operation',help='This contains the operation (show, enable, disable,set) or module to display',action='store')
parser.add_argument('module',help='This is the module to change',action='store',nargs='?')
parser.add_argument('level',help='This is the module level to change',action='store',nargs='?')
parser.add_argument('sublevel',help='This is the module sublevel to change',action='store',nargs='?')
parser.add_argument('-file',help='This is the config file to update',action='store',required=False)
parser.add_argument('-d',help='Enable debug printing',action='store_true',required=False)

_args = vars(parser.parse_args())

__maps = {'ALL':'1'}

def __write_log_config():
    with open(_args['file'],'w+') as f:
        for _mod in __maps:
            if _mod == 'ALL':
                if _args['d']:
                    print ("ALL %s" % (__maps[_mod]))
                f.write("ALL %s\n" % (__maps[_mod]))
                continue
            for _lvl in __maps[_mod]:
                f.write("%s %s %s\n" % (_mod,_lvl,__maps[_mod][_lvl]))
                if _args['d']:
                    print ("%s %s %s" % ((_mod,_lvl,__maps[_mod][_lvl])))

def _parse_existing_file(name):
    try:
        with open(name,'r') as f:
            while True:
                _entry_whole = f.readline()
                if len(_entry_whole)==0: break
                if _entry_whole[len(_entry_whole)-1]=='\n':
                    _entry_whole = _entry_whole[:-1]
                _entry = _entry_whole.split(' ')

                #handle ALL (1/0)
                if len(_entry)==2:
                    if __log_enable_to_string(_entry[1])=='Disable':
                        __maps['ALL'] = _entry[1]
                    continue

                #handle MODULE level (1/0)
                if len(_entry)!=3:
                    print ("%s is an invalid line" %_entry_whole)
                    continue
                if not _entry[0] in __maps:
                    __maps[_entry[0]] = {}
                __maps[_entry[0]][_entry[1]] = _entry[2]
    except:
        if _args['d']:
            print('No file found at %s' % _args['file'])
            traceback.print_exc(file=sys.stdout)
        pass
    if _args['d']:
            print __maps
def __log_level_to_string(level):
    for i in _map_level_to_int:
        if _map_level_to_int[i]==level:
            return i
    #default
    for i in _map_level_to_int:
        return i

def __print_log_config():

    print('All logs levels - except info and debug - are enabled for all applications. The following overrides the default configuration')

    for i in __maps:

        if i == 'ALL':
            if __log_enable_to_string(__maps[i])=='Disable':
                print('All logs are disabled due to override flag')
            continue

        if _args['module']!=None and _args['module']!=i and _args['module']!='all':
            if _args['d']:
                print ('Skipping %s' % i)
            continue

        for lvl in __maps[i]:

            _setting = 'Disabled'
            if __maps[i][lvl]!=str(0):
                _setting = 'Enabled'

            print ("%s %s %s" % (i,__log_level_to_string(lvl),_setting))

def __valid_args_modlev():
    _mod = _args['module']
    _lev = _args['level']
    if _mod==None:
        print('This combination is not supported.  Please entry a log module id')
        sys.exit(1)


def __set_mod_level(mod,level,how):
    if not mod in __maps:
        __maps[mod] = {}


    if level=='all':
        for i in _map_level_to_int.keys():
            __maps[mod][_map_level_to_int[i]] = how
    else:
        __maps[mod][level] = how


def __enable_logging():
    __valid_args_modlev()

    _mod = _args['module']
    if _mod=='ALL':
        if _mod in __maps:
            __maps[_mod] = '1'
    else:
        _lev = _args['level']
        __set_mod_level(_mod,_lev,'1')

    if _args['d']:
        print __maps

    __write_log_config()

def __disable_logging():
    __valid_args_modlev()

    _mod = _args['module']
    if _mod=='ALL':
        __maps[_mod] = '0'

    else:
        _lev = _args['level']
        __set_mod_level(_mod,_lev,'0')

    if _args['d']:
        print __maps
    __write_log_config()

_operations={'show':__print_log_config,'set':__enable_logging,'enable':__enable_logging,'disable':__disable_logging}

def main():
    _def_file_path = '/etc/opx/evlog.cfg'
    global _args
    if  _args['d']:
         print _args

    if 'file' in _args and _args['file']==None:
        _args['file'] = _def_file_path

    if not _args['operation'] in _operations:
        if  _args['d']:
            print('Showing module %s' % _args['operation'])
        _args['module'] = _args['operation']
        _args['operation'] = 'show'
        if  _args['d']:
            print _args


    if 'level' in _args and _args['level']!=None:
        _args['level'] = _args['level'].lower()
        if _args['level']==None or _args['level'] not in _map_level_to_int:
            print('This combination is not supported.  Please enter a valid level')
            sys.exit(1)

        _args['level'] = str(_map_level_to_int[_args['level']])

    if 'level' in _args and _args['level']==None:
        _args['level'] = 'all'

    if 'module' in _args and _args['module']=='all':
        _args['module'] = _args['module'].upper()

    _parse_existing_file(_args['file'])

    if  _args['operation'] in _operations:
        _operations[_args['operation']]()

if __name__ == '__main__':
    main()
